﻿using System;
using System.Collections.Generic;
using System.Drawing;
using kp.koordinator.contract;
using NUnit.Framework;

namespace kp.koordinator.tests
{
  [TestFixture]
  public class TestKoordinator
  {
    [Test]
    public void Test_ob_Aufrufparameter_und_Teilergebnisse_an_Compiler_und_Rechenwerk_weitergereicht_werden()
    {
      PointF[] simuliertesRechenwerkErgebnis;
      MockCompiler mockCompiler;
      MockRechenwerk mockRechenwerk;

      var simuliertesCompilerErgebnis = Arrange(out simuliertesRechenwerkErgebnis, out mockCompiler, out mockRechenwerk);

      var sut = new Koordinator(mockCompiler, mockRechenwerk);
      var sutErgebnis = sut.Berechne("Formel", -5, 5, 100);

      Assert(mockCompiler, mockRechenwerk, simuliertesCompilerErgebnis, simuliertesRechenwerkErgebnis, sutErgebnis);
    }

    private static void Assert(MockCompiler mockCompiler, MockRechenwerk mockRechenwerk, Func<double, double> simuliertesCompilerErgebnis, PointF[] simuliertesRechenwerkErgebnis, IEnumerable<PointF> sutErgebnis)
    {
      
      NUnit.Framework.Assert.That(mockCompiler.InputFormel, Is.EqualTo("Formel"));

      NUnit.Framework.Assert.AreSame(mockRechenwerk.Funktion, simuliertesCompilerErgebnis);

      NUnit.Framework.Assert.That(mockRechenwerk.XMin, Is.EqualTo(-5));
      NUnit.Framework.Assert.That(mockRechenwerk.XMax, Is.EqualTo(5));
      NUnit.Framework.Assert.That(mockRechenwerk.Werteanzahl, Is.EqualTo(100));

      NUnit.Framework.Assert.AreSame(sutErgebnis, simuliertesRechenwerkErgebnis);
    }

    private static Func<double, double> Arrange(out PointF[] simuliertesRechenwerkErgebnis, out MockCompiler mockCompiler, out MockRechenwerk mockRechenwerk)
    {
      Func<double, double> simuliertesCompilerErgebnis = 
        x => Convert.ToDouble("Egal was hier steht, es geht nur um die Referenz auf diese Funktion, die getestet wird");

      mockCompiler = new MockCompiler(simuliertesCompilerErgebnis);

      simuliertesRechenwerkErgebnis = new[]
                                        {
                                          new PointF(10, 20),
                                          new PointF(-10, 10),
                                          new PointF(30, 40),
                                        };

      mockRechenwerk = new MockRechenwerk(simuliertesRechenwerkErgebnis);
      return simuliertesCompilerErgebnis;
    }
  }
}
